let utils = module.exports;

utils.log = function (level, msg) {
    console.log(msg);
};

utils.info = function (msg) {
    utils.log('info', msg);
};

utils.warn = function (msg) {
    utils.log('warn', msg);
};

utils.error = function (msg) {
    utils.log('error', msg);
};

utils.debug = function (msg) {
    utils.log('debug', msg);
};

utils.trace = function (msg) {
    utils.log('trace', msg);
};

utils.clone = function (o) {
    let x = {};
    for (let p in o) {
        x[p] = o[p];
    }
    return x;
};

utils.drawTextWithShadow = function (ctx, text, x, y) {
    ctx.save();
    ctx.fillStyle = 'black';
    ctx.fillText(text, x + 1, y + 1);
    ctx.fillText(text, x - 1, y + 1);
    ctx.fillText(text, x + 1, y - 1);
    ctx.fillText(text, x - 1, y - 1);
    ctx.restore();
    ctx.fillText(text, x, y);
};

class TextWriterHelper {
    constructor(ctx, left, height, maxWidth, size, font) {
        this.ctx = ctx;
        this.height = height;
        this.maxWidth = maxWidth;
        this.left = left;
        this.size = size;
        this.font = font;

        this.NEW_LINE_HEIGHT = 2;
        this.NEW_PARA_HEIGHT = 5;
    }

    write(textConfArray) {
        let startWidth = 0;
        for (let elem of textConfArray) {
            this.ctx.textAlign = "left";
            this.ctx.font = '' + this.size + 'px 微软雅黑';
            this.ctx.fillStyle = elem.color;
            startWidth = this.__write(elem.text, startWidth, this.maxWidth, false);
        }
        this.__newLine();
    }

    __newLine() {
        this.height += this.size + this.NEW_LINE_HEIGHT;
    }

    __newPara() {
        this.height += this.NEW_PARA_HEIGHT;
    }

    __write(text, startWidth, endWidth, autoNewLine) {
        while (true) {
            for (let i = text.length; i > 0; --i) {
                let s = text.substring(0, i);
                let width = this.ctx.measureText(s).width;
                if (width < (endWidth - startWidth)) {
                    this.ctx.fillText(s, this.left + startWidth, this.height);
                    startWidth = startWidth + width;
                    if (autoNewLine) {
                        this.__newLine();
                        startWidth = 0;
                    }
                    text = text.substring(i);
                    i = text.length + 1;
                }
            }
            if (text.length) {
                this.__newLine();
                startWidth = 0;
            } else {
                break;
            }
        }
        if (autoNewLine) {
            this.__newPara();
        }
        return startWidth;
    }

    writeLine(text) {
        this.ctx.textAlign = "left";
        this.ctx.font = '' + this.size + 'px ' + this.font;
        let texts = text.split('\n');
        for (let t of texts) {
            this.__write(t, 0, this.maxWidth, true);
        }
    }

    calculateDrawLineHeight(textArray) {
        this.ctx.save();
        this.ctx.fillStyle = 'rgba(0,0,0,0)';
        for (let text of textArray) {
            this.writeLine(text);
        }
        this.ctx.restore();
        return this.height;
    }
}

utils.TextWriterHelper = TextWriterHelper;

utils.drawArcRec = function (ctx, x, y, width, height, arcPixel) {
    let r = arcPixel;
    let leftTopTop = [x + arcPixel, y];
    let leftTopLeft = [x, y + arcPixel];
    let leftBotLeft = [x, y + height - arcPixel];
    let leftBotBot = [x + arcPixel, y + height];
    let rightBotBot = [x + width - arcPixel, y + height];
    let rightBotRight = [x + width, y + height - arcPixel];
    let rightTopRight = [x + width, y + arcPixel];
    let rightTopTop = [x + width - arcPixel, y];
    ctx.save();
    ctx.moveTo(leftTopTop[0], leftTopTop[1]);
    ctx.arcTo(x, y, leftTopLeft[0], leftTopLeft[1], r);
    ctx.lineTo(leftBotLeft[0], leftBotLeft[1]);
    ctx.arcTo(x, y + height, leftBotBot[0], leftBotBot[1], r);
    ctx.lineTo(rightBotBot[0], rightBotBot[1]);
    ctx.arcTo(x + width, y + height, rightBotRight[0], rightBotRight[1], r);
    ctx.lineTo(rightTopRight[0], rightTopRight[1]);
    ctx.arcTo(x + width, y, rightTopTop[0], rightTopTop[1], r);
    ctx.lineTo(leftTopTop[0], leftTopTop[1]);
    ctx.restore();
};

utils.drawDashRect = function (ctx, minX, minY, width, height, startX, linePixels, dashPixels) {
    let maxX = minX + width;
    let maxY = minY + height;

    function getEndPointWithDirection(x, y, direction, len) {
        // direction
        // 0:right
        // 1:down
        // 2:left
        // 3:up
        if (direction === 0) {
            if (x + len > maxX) {
                return {x: maxX, y: y, direction: 1, len: len - (maxX - x)};
            } else {
                return {x: x + len, y: y, direction: 0, len: 0};
            }
        } else if (direction == 1) {
            if (y + len > maxY) {
                return {x: x, y: maxY, direction: 2, len: len - (maxY - y)};
            } else {
                return {x: x, y: y + len, direction: 1, len: 0};
            }
        } else if (direction == 2) {
            if (x - len < minX) {
                return {x: minX, y: y, direction: 3, len: len - (x - minX)};
            } else {
                return {x: x - len, y: y, direction: 2, len: 0};
            }
        } else {
            if (y - len < minY) {
                return {x: x, y: minY, direction: 0, len: len - (y - minY)};
            } else {
                return {x: x, y: y - len, direction: 3, len: 0};
            }
        }
    }

    let currentX = minX + startX - linePixels;
    let currentY = minY;
    let direction = 0;
    let directionWas1 = false;
    let doMove = true;
    let len = dashPixels;

    ctx.save();
    ctx.beginPath();
    while ((direction == 0 && !directionWas1) || (direction != 0 && directionWas1)) {
        let r = getEndPointWithDirection(currentX, currentY, direction, len);
        currentX = r.x;
        currentY = r.y;
        direction = r.direction;
        len = r.len;

        if (doMove) {
            ctx.moveTo(currentX, currentY);
        } else {
            ctx.lineTo(currentX, currentY);
        }

        if (len === 0) {
            doMove = !doMove;
            if (doMove) {
                len = dashPixels;
            } else {
                len = linePixels;
            }
        }

        if (direction == 1) {
            directionWas1 = true;
        }
    }
    ctx.stroke();
    ctx.restore();
};

utils.drawRectTri = function (ctx, x, y, width, height, angle) {
    let deltaY = width / 2 / Math.tan(angle);
    ctx.save();
    ctx.moveTo(x, y);
    ctx.lineTo(x, y + height);
    ctx.lineTo(x + width / 2, y + height - deltaY);
    ctx.lineTo(x + width, y + height);
    ctx.lineTo(x + width, y);
    ctx.lineTo(x + width / 2, y - deltaY);
    ctx.closePath();
    ctx.restore();
};
